#!/usr/bin/env gosh
(use srfi-1)
(use sxml.ssax)
(use sxml.serializer)
(use sxml.tools)
(use sxml.sxpath)
(use sxml.tree-trans)
(use gauche.sequence)
(use gauche.process)
(use gauche.parseopt)

(define (main args)
  (let-args (cdr args)
      ((option-n "n|node=s" "")
       (option-k "k|key=s" "")
       (cmd    "c|cmd=s" #f)
       (debug  "p" #f)
       (print-marked "m" #f)
       . file)
    (define sxml (if (null? file)
		   (ssax:xml->sxml (current-input-port) '())
		   (call-with-input-file (car file) (lambda (in)
						      (ssax:xml->sxml in '())))))
    (let ((nodes ((sxpath option-n) sxml))
	  (keys ((sxpath option-k) sxml)))
      (cond
       (debug
	(for-each print keys))
       (cmd 
	(cmd! sxml cmd nodes keys)
	(print (srl:sxml->html (pre-post-order
				sxml
				`((remove . ,(lambda _ ""))
				  (*text* . ,(lambda (trigger x) x))
				  (*default* . ,(lambda x x)))))))
       (else
	(print (srl:sxml->html sxml))))))
  (exit 0))

(define (cmd! sxml cmd nodes keys)
  (define ht (make-hash-table 'string=?))
  (for-each-with-index (lambda (i key)
			 (hash-table-update! ht key (lambda (x)
							(append x (list i)))
					     '()))
		       keys)
    (let ((nodes-contents (map sxml:content nodes))
	  (cmd-result (map (lambda (x)
			     (hash-table-pop! ht x))
			   (run-cmd cmd keys))))
      (for-each (lambda (x place)
		  (sxml:change-content! x (list-ref nodes-contents place)))
		nodes
		cmd-result)
      (for-each (lambda (place)
       		  (sxml:change-name! (list-ref nodes place) 'remove))
		(lset-difference eq? (iota (length keys)) cmd-result))))

(define (run-cmd cmd keys)
 (call-with-process-io
  cmd
  (lambda (in out)
    (for-each (lambda (x)
		(format out "~a\n" x))
	      keys)
    (flush out)
    (close-output-port out)
    (port->string-list in))
  :on-abnormal-exit :ignore))
